x86_32: Relocate multiboot modules to below 1GB.
authorKeir Fraser <keir.fraser@citrix.com>
Tue, 23 Mar 2010 07:28:33 +0000 (07:28 +0000)
committerKeir Fraser <keir.fraser@citrix.com>
Tue, 23 Mar 2010 07:28:33 +0000 (07:28 +0000)
Otherwise Xen cannot access them later during boot. GRUB2 places
modules as high as possible below 4GB, which has been causing boot
failure.

Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
xen/arch/x86/boot/Makefile
xen/arch/x86/boot/build32.mk
xen/arch/x86/boot/reloc.c

index 90856f918e77ce8ffb91467905ebe397a57360e7..630b19d027d8ce5d968c491a7c28d8d63fd6af0a 100644 (file)
@@ -4,6 +4,6 @@ head.o: reloc.S
 
 BOOT_TRAMPOLINE := $(shell sed -n 's,^\#define[[:space:]]\+BOOT_TRAMPOLINE[[:space:]]\+,,p' $(BASEDIR)/include/asm-x86/config.h)
 %.S: %.c
-       RELOC=$(BOOT_TRAMPOLINE) $(MAKE) -f build32.mk $@
+       RELOC=$(BOOT_TRAMPOLINE) XEN_BITSPERLONG=$(patsubst x86_%,%,$(TARGET_SUBARCH)) $(MAKE) -f build32.mk $@
 
 reloc.S: $(BASEDIR)/include/asm-x86/config.h
index 01f7480b52e23b8746dc8e59b0e4e723d65a944b..0de9c15af2878cca6dea96eb7f996e8e2c8c83ef 100644 (file)
@@ -22,6 +22,6 @@ CFLAGS += -Werror -fno-builtin -msoft-float
        $(LD) $(LDFLAGS_DIRECT) -N -Ttext $(RELOC) -o $@ $<
 
 %.o: %.c
-       $(CC) $(CFLAGS) -c $< -o $@
+       $(CC) $(CFLAGS) -DXEN_BITSPERLONG=$(XEN_BITSPERLONG) -c $< -o $@
 
 reloc.o: $(BASEDIR)/include/asm-x86/config.h
index e3333d36b8880e145a6fe64f258472561b898c28..233a94f3474a7e27c411b8bb1e395fd2d972f9d2 100644 (file)
@@ -70,8 +70,28 @@ multiboot_info_t *reloc(multiboot_info_t *mbi_old)
             (module_t *)mbi->mods_addr, mbi->mods_count * sizeof(module_t));
         mbi->mods_addr = (u32)mods;
         for ( i = 0; i < mbi->mods_count; i++ )
+        {
+#if XEN_BITSPERLONG == 32
+            /*
+             * 32-bit Xen only maps bottom 1GB of memory at boot time.
+             * Relocate modules which extend beyond this (GRUB2 in particular
+             * likes to place modules as high as possible below 4GB).
+             */
+#define BOOTMAP_END (1ul<<30) /* 1GB */
+            static void *mod_alloc = (void *)BOOTMAP_END;
+            u32 mod_len = mods[i].mod_end - mods[i].mod_start;
+            if ( mods[i].mod_end > BOOTMAP_END )
+            {
+                mod_alloc = (void *)
+                    (((unsigned long)mod_alloc - mod_len) & ~15ul);
+                mods[i].mod_start = (u32)memcpy(
+                    mod_alloc, (char *)mods[i].mod_start, mod_len);
+                mods[i].mod_end = mods[i].mod_start + mod_len;
+            }
+#endif
             if ( mods[i].string )
                 mods[i].string = (u32)reloc_mbi_string((char *)mods[i].string);
+        }
     }
 
     if ( mbi->flags & MBI_MEMMAP )